import 'dart:math';

import 'package:flutter/widgets.dart';

///页面关键点位坐标集合
class PaperPoint {
  //手指拉拽点 已知
  Point<double> a;

  // c区域影深
  final double elevationC;

  //右下角的点 已知
  late Point<double> f;

  //距离该坐标点为10并和该直线相交的的坐标点
  late Point<double> p;
  late Point<double> p2;

  //
  // //贝塞尔点(e为控制点)
  late Point<double> b, c, d, e;

  // //贝塞尔点(h为控制点)
  late Point<double> h, i, j, k;

  //eh实际为af中垂线，g为ah和af的交点
  late Point<double> g;

  late Size size;

  late double ahK;
  late double ahB;

  PaperPoint(
    this.a,
    this.size, {
    this.elevationC = 10,
  }) {
    //屏幕右下角
    f = Point(size.width, size.height);

    //g点分割af可得
    g = Point((a.x + f.x) / 2, (a.y + f.y) / 2);

    //△egf、△emg、△mfg 为三个直角三角形，由直角三角形相似原理可知这三个三角型两两相似，所以，△emg相似△mfg
    //gm/em= mf/gm 变形后 em= gm*gm/mf
    e = Point(g.x - (pow(f.y - g.y, 2) / (f.x - g.x)), f.y);

    double cx = e.x - (f.x - e.x) / 2;
    if (a.x > 0) {
      //临界点,防止c点x轴出边界，利用按照三角形相似同比例比例缩放
      //fb1/fc1 = fb/fc;
      //从而得到，fb1= fc1*fb/fc;   设fc1 = 屏幕最大宽度 size.width
      if (cx <= 0) {
        //实际c横坐标
        double fc = f.x - cx;
        //实际a横坐标
        double fb = f.x - a.x;
        //实际a纵坐标
        double ab = f.y - a.y;

        //缩放后a横坐标
        double fb1 = size.width * fb / fc;
        //缩放后a纵坐标，同理 a1b1/fb1 =  ab / fb
        double a1b1 = fb1 * ab / fb;

        a = Point(f.x - fb1, f.y - a1b1);
        g = Point((a.x + f.x) / 2, (a.y + f.y) / 2);
        e = Point(g.x - (pow(f.y - g.y, 2) / (f.x - g.x)), f.y);
        //c 点和纵轴重合
        cx = 0;
      }
    }

    //证明ce 是ef 的一半
    //已知△aef 是等腰三角形所以有线段ea = ef 角afe = 角ban ，
    //因为 角afe + 角pce  = 90度 ,  角ban + 角abn   = 90度
    //所以 角pce = 角abn
    //因为 角abn 和 角pbe 是对角，所以角pce = 角pbe，三角形ceb是等腰三角形，ce = eb
    //因为n是ag线段中点，cj 平行 eh ,三角形相似原理， 顾b是ea的中线, 所以 ef = 2*ce
    c = Point(cx, f.y);

    //h,j 同理 e,c
    h = Point(f.x, g.y - (pow((f - g).x, 2) / (f.y - g.y)));
    j = Point(f.x, h.y - (f.y - h.y) / 2);

    //c 和 j 直线方程
    double k1 = towPointKb(c, j);
    double b1 = towPointKb(c, j, isK: false);
    //a 和 e 直线方程
    double k2 = towPointKb(a, e);
    double b2 = towPointKb(a, e, isK: false);
    //a 和 h 直线方程
    double k3 = towPointKb(a, h);
    double b3 = towPointKb(a, h, isK: false);

    //求线段 cj 和 ae 交点
    b = Point((b2 - b1) / (k1 - k2), (b2 - b1) / (k1 - k2) * k1 + b1);
    //求线段 cj 和 ah 交点
    k = Point((b3 - b1) / (k1 - k3), (b3 - b1) / (k1 - k3) * k1 + b1);

    //因为 d 是 ep 的中线 ，p点为cb的中点。
    //所以 p.x = (b.x+c.x)/2; ,  d.x = (e.x+p.x)/2;
    //所以 p.y = (b.y+c.y)/2; ,  d.y = (e.y+p.y)/2;
    d = Point(((c.x + b.x) / 2 + e.x) / 2, ((c.y + b.y) / 2 + e.y) / 2);
    //原理同d
    i = Point(((j.x + k.x) / 2 + h.x) / 2, ((j.y + k.y) / 2 + h.y) / 2);

    //已知a坐标点在一条直线上(a 到 h 的直线方程)，距离该坐标点为10并和该直线相交的的坐标点
    //利用圆的交点，或者三角函数，勾股定理+相似都可以求出来
    p = toP(a, towPointKb(a, h), towPointKb(a, h, isK: false), elevationC);
    p2 = toP(a, towPointKb(a, e), towPointKb(a, e, isK: false), elevationC);
  }

  Point<double> toP(Point<double> p, double k, double b, double jl) {
    double x = 0.0;
    double y = 0.0;

    if (k > 0 || a.y >= h.y) {
      x = a.x - sqrt(jl * jl / (1 + (k * k)));
      y = a.y - sqrt(jl * jl / (1 + (k * k))) * k;
    } else {
      x = a.x + sqrt(jl * jl / (1 + (k * k)));
      y = a.y + sqrt(jl * jl / (1 + (k * k))) * k;
    }

    return Point<double>(x, y);
  }

  /// 两点求直线方程 y = kx + b  :
  /// p1.y-p2.y = (k*p1.x + b) - (k*p2.x + b),
  /// 经变形后得到 p1.y-p2.y = k*p1.x - k*p2.x,
  /// 经变形后得到 k= (p1.y-p2.y)/(p1.x -p2.x)
  static double towPointKb(Point<double> p1, Point<double> p2,
      {bool isK = true}) {
    /// 求得两点斜率
    double k = 0;
    double b = 0;
    // 防止除数 = 0 出现的计算错误 a e x轴重合
    if (p1.x == p2.x) {
      k = (p1.y - p2.y) / (p1.x - p2.x - 1);
    } else {
      k = (p1.y - p2.y) / (p1.x - p2.x);
    }
    b = p1.y - k * p1.x;
    if (isK) {
      return k;
    } else {
      return b;
    }
  }

  //两条直线的交点
  static Point<double> toTwoPoint(
      Point<double> a, Point<double> b, Point<double> m, Point<double> n) {
    double k1 = towPointKb(a, b);
    double b1 = towPointKb(a, b, isK: false);

    double k2 = towPointKb(m, n);
    double b2 = towPointKb(m, n, isK: false);

    /**
     * 求解交点x的过程
     * p1.y=k1*p1.x+b1
     * p2.y=k2*p2.x+b2
     * k2*p2.x+b2 = k1*p1.x+b1
     * b2-b1 = k1*p1.x - k2*p2.x
     * (b2-b1）/  (k1-k2) = x
     */
    return Point((b2 - b1) / (k1 - k2), (b2 - b1) / (k1 - k2) * k1 + b1);
  }

  @override
  String toString() {
    // TODO: implement toString
    return "x:${a.x} y:${a.y}";
  }
}
